import { createElement, nop } from "../../lib/skeleton/index.js";
import rxjs, { effect, onClick, preventDefault } from "../../lib/rx.js";
import { qs } from "../../lib/dom.js";
import { animate } from "../../lib/animate.js";
import { loadCSS } from "../../helpers/loader.js";

import { getAction$, setAction } from "./state_newthing.js";
import { currentPath } from "./helper.js";
import { mkdir as mkdir$, touch as touch$ } from "./model_files.js";
import { mkdir as mkdirVL, touch as touchVL, withVirtualLayer } from "./model_virtual_layer.js";

const touch = (path) => withVirtualLayer(
    touch$(path),
    touchVL(path),
);
const mkdir = (path) => withVirtualLayer(
    mkdir$(path),
    mkdirVL(path),
);

const IMAGE = {
    FILE: "",
    FOLDER: "",
    TRASH: "",
};

export default async function(render) {
    const $node = createElement(`
        <div class="component_newitem container" id="newthing">
            <div class="component_thing">
                <div class="mouse-is-hover highlight box flex">
                    <img class="component_icon" draggable="false" alt="directory" aria-hidden="true">
                    <span class="file-details">
                        <form class="full-width">
                            <input type="text" name="name" value="" class="full-width">
                            <input type="hidden" name="type" value="">
                        </form>
                    </span>
                    <span class="component_action">
                        <div class="action">
                            <div role="button">
                                <img class="component_icon" draggable="false" src="${IMAGE.TRASH}" alt="trash">
                            </div>
                        </div>
                    </span>
                </div>
            </div>
        </div>
    `);
    $node.classList.add("hidden");

    const $input = qs($node, "input[type=\"text\"]");
    const $icon = qs($node, ".component_icon");
    const $remove = qs($node, ".action");

    // feature1: setup the dom
    effect(getAction$().pipe(
        rxjs.map((targetName) => {
            if (targetName === "NEW_FILE") return {
                targetName,
                alt: "file",
                img: IMAGE.FILE,
            };
            if (targetName === "NEW_FOLDER") return {
                targetName,
                alt: "directory",
                img: IMAGE.FOLDER,
            };
            return null;
        }),
        rxjs.filter((val) => val),
        rxjs.tap(async({ img, alt }) => {
            $icon.setAttribute("src", `${img}`);
            $icon.setAttribute("alt", alt);
            $input.value = "";
            $input.nextElementSibling.setAttribute("name", alt);
            let done = Promise.resolve(nop);
            if ($node.classList.contains("hidden")) done = animate($node, {
                keyframes: [{ height: `0px` }, { height: "50px" }],
                time: 100,
                fill: "forwards",
            });
            $node.classList.remove("hidden");
            render($node);
            await done;
            await new Promise(requestAnimationFrame);
            $input.focus();
        }),
    ));

    // feature2: remove the component
    effect(rxjs.merge(
        rxjs.merge(
            onClick($remove),
            rxjs.fromEvent(window, "keydown").pipe(rxjs.filter((e) => e.keyCode === 27)),
        ).pipe(rxjs.tap(() => setAction(null))),
        getAction$().pipe(
            rxjs.filter((actionName) => !actionName),
        ),
    ).pipe(rxjs.tap(async() => {
        await animate($node, {
            keyframes: [{ height: "50px" }, { height: `0px` }],
            time: 50,
            fill: "backwards",
        });
        $node.classList.add("hidden");
    })));

    // feature3: submit form
    effect(rxjs.fromEvent($node, "submit").pipe(
        preventDefault(),
        rxjs.filter(() => $input.value),
        rxjs.mergeMap(() => {
            window.dispatchEvent(new KeyboardEvent("keydown", { keyCode: 27 })); // close
            const type = $input.nextElementSibling.getAttribute("name");
            if (type === "file") return touch(currentPath() + $input.value);
            return mkdir(currentPath() + $input.value + "/");
        }),
        rxjs.catchError((err) => console.log("ERR", err)),
    ));
}

export function init() {
    return loadCSS(import.meta.url, "./ctrl_newitem.css");
}
